
"""
    预测服务器
    启动脚本 nohup python predict_server.py > server.log 2>&1 &


"""

from http.server import HTTPServer, BaseHTTPRequestHandler
import json
from tensorflow import keras
import numpy as np

host = ('localhost', 8865)

nnm_dict = {}


def compute_nnm(file_name):
    model = nnm_dict.get(file_name)
    if model is None:
        model = NNModel(file_name)
        nnm_dict[file_name] = model
        return model
    else:
        return model


def release_nnm(file_name):
    del nnm_dict[file_name]


class NNModel:

    def __init__(self, model_file):
        self.model = keras.models.load_model(model_file)

    """
        和 训练的时候保持一致
    """

    def __normalization(self, array):
        # 根据boll来计算
        ptp = array[:, 6:9].ptp() * 1.5
        volume_ptp = array[:, 4:5].ptp()
        position_ptp = array[:, 5:6].ptp()
        # macd 固定即可
        macd = 10
        if ptp == 0 or volume_ptp == 0 or position_ptp == 0:
            # 存在错误数据
            return
        # new_features.append((f - means) / std)
        denominator = [ptp, ptp, ptp, ptp, volume_ptp, position_ptp, ptp, ptp, ptp, macd, macd, macd]
        bm = array[0][4]
        start = [bm, bm, bm, bm, array[0][4], array[0][5], bm, bm, bm, 0, 0, 0]
        return (array - start) / denominator

    def predict(self, dataset):
        dataset = np.array(dataset).astype(np.float32)
        dataset = self.__normalization(dataset)
        dataset = np.array([dataset])
        return self.model.predict(dataset)


class Request(BaseHTTPRequestHandler):

    def __get_result(self, result, success=True):
        return {
            "result": result,
            "success": success
        }

    def do_GET(self):
        self.send_response(200)
        self.send_header('Content-type', 'application/json')
        self.end_headers()
        self.wfile.write(json.dumps(self.__get_result("this is Neural network model server")).encode())

    def do_POST(self):
        datas = self.rfile.read(int(self.headers.get('Content-Length'))).decode('utf-8')
        datas = json.loads(datas)
        print("data:", datas)
        self.send_response(200)
        self.send_header('Content-type', 'application/json')
        self.end_headers()
        try:
            op = datas.get("op")
            file_name = datas.get("fileName")
            dataset = datas.get("dataset")
            dataset = np.array(dataset)
            result = self.__handle(op, file_name, dataset)
            self.wfile.write(json.dumps(self.__get_result(result)).encode())
        except Exception as e:
            print(e)
            self.wfile.write(json.dumps(self.__get_result(str(e), success=False)).encode())

    def __handle(self, op, file_name, dataset):
        if op == "release":
            release_nnm(file_name)
            return ""
        elif op == "predict":
            model = compute_nnm(file_name)
            dataset = np.array(dataset)
            result = model.predict(dataset)
            return result[0].tolist()
        else:
            return "Unsupport"


if __name__ == '__main__':
    server = HTTPServer(host, Request)
    print("Starting server, listen at: %s:%s" % host)
    server.serve_forever()
